package com.test;

import com.imooc.Application;
import com.imooc.es.pojo.Stu;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class})
public class EsTestByDoc {

    @Autowired
    private ElasticsearchTemplate esTemplate;


    @Test
    public void updateStuDoc(){
        // 1.构建要更新的内容
        Map<String,Object> sourceMap = new HashMap<>();
        sourceMap.put("sign","I am not super man");
        sourceMap.put("money",88.6f);
        sourceMap.put("age",33);
        // 2. 生成IndexRequest，将要更新的内容放入IndexRequest中
        IndexRequest indexRequest = new IndexRequest();
        indexRequest.source(sourceMap);
        // 3. 生成UpdateQuery ,需要指定索引和文档Id以及IndexRequest(更新数据）
        // update stu set sign = '' and money = '' and age = '' where docId = '1002'
        UpdateQuery updateQuery = new UpdateQueryBuilder().withClass(Stu.class)
                .withId("1002").withIndexRequest(indexRequest).build();
        esTemplate.update(updateQuery);
    }

    /**
     * 查询数据
     */
    @Test
    public void searchStuDoc(){
        GetQuery getQuery  = new GetQuery();
        getQuery.setId("1002");
        Stu stu = esTemplate.queryForObject(getQuery, Stu.class);
        System.out.println(stu);
    }

    /**
     * 删除文档数据
     */
    @Test
    public void delStuDoc(){
        esTemplate.delete(Stu.class,"1002");
    }

    /**
     * 分页搜索
     */
    @Test
    public void searchStuDocByPage(){

        Pageable pageable = PageRequest.of(0,10);

        SearchQuery query = new NativeSearchQueryBuilder()
                                .withQuery(QueryBuilders.matchQuery("description","save man")) // 构建查询条件
                                .withPageable(pageable) // 构建分页条件
                                .build();
        AggregatedPage<Stu> pageStu = esTemplate.queryForPage(query,Stu.class);
        System.out.println("检索后的总分页数目为："+pageStu.getTotalPages());
        // 文档数据
        List<Stu> stuList = pageStu.getContent();
        for(Stu stu : stuList){
            System.out.println(stu);
        }
    }

    /**
     * 实现高亮显示
     */
    @Test
    public void highlightStuDoc(){
        Pageable pageable = PageRequest.of(0,10);

        String preTag = "<font color='red'>";
        String postTag = "</font>";

        SearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery("description","save man")) // 构建查询条件
                .withPageable(pageable) // 构建分页条件
                .withHighlightFields(new HighlightBuilder.Field("description")
                                    .preTags(preTag)
                                    .postTags(postTag)) // 构建高亮条件
                .build();
        AggregatedPage<Stu> pageStu = esTemplate.queryForPage(query,Stu.class, new SearchResultMapper() {
            // 对查询出来的结果做一个映射，自定义映射
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
                List<Stu> stuListHighlt = new ArrayList<>();
                SearchHits searchHits = response.getHits();
                for(SearchHit h : searchHits){
                   Stu stuHlL = mapSearchHit(h,Stu.class);
                    stuListHighlt.add(stuHlL);
                }
                if(stuListHighlt.size() >0){
                    return new AggregatedPageImpl<>((List<T>)stuListHighlt);
                }
                return null;
            }

            @Override
            public <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
                HighlightField hlField = searchHit.getHighlightFields().get("description");
                String hldesc = hlField.getFragments()[0].toString();
                Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
                Object stuId = (Object)sourceAsMap.get("stuId");
                String name = (String)sourceAsMap.get("name");
                Integer age = (Integer) sourceAsMap.get("age");
                String sign = (String) sourceAsMap.get("sign");
                Object money = (Object) sourceAsMap.get("money");

                Stu stuHlL = new Stu();
                stuHlL.setDescription(hldesc);
                stuHlL.setStuId(Long.valueOf(stuId.toString()));
                stuHlL.setName(name);
                stuHlL.setAge(age);
                stuHlL.setSign(sign);
                stuHlL.setMoney(Float.valueOf(money.toString()));
                return (T)stuHlL;
            }
        });
        System.out.println("检索后的总分页数目为："+pageStu.getTotalPages());
        // 文档数据
        List<Stu> stuList = pageStu.getContent();
        for(Stu stu : stuList){
            System.out.println(stu);
        }
    }


    /**
     * 搜索+排序
     */
    @Test
    public void searchStuDocByPageAndSort(){

        Pageable pageable = PageRequest.of(0,10);

        // 排序条件
        SortBuilder sortBuilder = new FieldSortBuilder("money")
                                    .order(SortOrder.DESC);
        SortBuilder sortBuilderAge = new FieldSortBuilder("age")
                .order(SortOrder.ASC);


        SearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery("description","save man")) // 构建查询条件
                .withPageable(pageable) // 构建分页条件
                .withSort(sortBuilder) // 构建排序条件
                .withSort(sortBuilderAge) // 多条件排序
                .build();
        AggregatedPage<Stu> pageStu = esTemplate.queryForPage(query,Stu.class);
        System.out.println("检索后的总分页数目为："+pageStu.getTotalPages());
        // 文档数据
        List<Stu> stuList = pageStu.getContent();
        for(Stu stu : stuList){
            System.out.println(stu);
        }
    }

}
